package com.ai.service.impl;

import com.ai.entity.SysPermissionEntity;
import com.ai.entity.SysRolePermissionEntity;
import com.ai.entity.SysUserRoleEntity;
import com.ai.exception.BusinessException;
import com.ai.exception.code.BaseResponseCode;
import com.ai.mapper.SysPermissionMapper;
import com.ai.mapper.SysRolePermissionMapper;
import com.ai.mapper.SysUserRoleMapper;
import com.ai.service.PermissionService;
import com.ai.service.RolePermissionService;
import com.ai.service.UserRoleService;
import com.ai.utils.AssertUtil;
import com.ai.utils.ConvertUtils;
import com.ai.web.request.PermissionAddReq;
import com.ai.web.response.PermissionNodeResp;
import com.ai.web.response.SysPermissionResp;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 权限管理
 */
@Service
@Slf4j
public class PermissionServiceImpl implements PermissionService {

    @Resource
    private UserRoleService userRoleService;

    @Resource
    private RolePermissionService rolePermissionService;

    @Resource
    private SysUserRoleMapper sysUserRoleMapper;

    @Resource
    private SysRolePermissionMapper sysRolePermissionMapper;

    @Resource
    private SysPermissionMapper sysPermissionMapper;

    @Override
    public SysPermissionEntity getById(String id) {
        return sysPermissionMapper.selectById(id);
    }

    @Override
    public void addPermission(PermissionAddReq permissionAddReq) {
        SysPermissionEntity sysPermission = ConvertUtils.convert(permissionAddReq, SysPermissionEntity.class);
        verifyFormPid(sysPermission);
        sysPermissionMapper.insert(sysPermission);
    }

    /**
     * 操作后的菜单类型是目录的时候 父级必须为目录
     * 操作后的菜单类型是菜单的时候，父类必须为目录类型
     * 操作后的菜单类型是按钮的时候 父类必须为菜单类型
     */
    @Override
    public void verifyFormPid(SysPermissionEntity sysPermission) {
        SysPermissionEntity parent;
        parent = sysPermissionMapper.selectById(sysPermission.getPid());
        switch (sysPermission.getType()) {
            case 1:
                if (parent != null) {
                    if (parent.getType() != 1) {
                        throw new BusinessException(BaseResponseCode.OPERATION_MENU_PERMISSION_CATALOG_ERROR);
                    }
                } else if (!"0".equals(sysPermission.getPid())) {
                    throw new BusinessException(BaseResponseCode.OPERATION_MENU_PERMISSION_CATALOG_ERROR);
                }
                break;
            case 2:
                if (parent == null || parent.getType() != 1) {
                    throw new BusinessException(BaseResponseCode.OPERATION_MENU_PERMISSION_MENU_ERROR);
                }
                if (StringUtils.isEmpty(sysPermission.getUrl())) {
                    throw new BusinessException(BaseResponseCode.OPERATION_MENU_PERMISSION_URL_NOT_NULL);
                }

                break;
            case 3:
                if (parent == null || parent.getType() != 2) {
                    throw new BusinessException(BaseResponseCode.OPERATION_MENU_PERMISSION_BTN_ERROR);
                }
                if (StringUtils.isEmpty(sysPermission.getPerms())) {
                    throw new BusinessException(BaseResponseCode.OPERATION_MENU_PERMISSION_URL_PERMS_NULL);
                }
                if (StringUtils.isEmpty(sysPermission.getUrl())) {
                    throw new BusinessException(BaseResponseCode.OPERATION_MENU_PERMISSION_URL_NOT_NULL);
                }
                break;
            default:
        }
    }

    /**
     * 通过用户ID查询权限
     *
     * @param userId userId
     * @return
     */
    @Override
    public List<SysPermissionEntity> getPermission(String userId) {
        List<String> roleIds = userRoleService.getRoleIdsByUserId(userId);
        if (CollectionUtils.isEmpty(roleIds)) {
            return null;
        }
        List<String> permissionIds = rolePermissionService.getPermissionIds(roleIds);
        if (CollectionUtils.isEmpty(permissionIds)) {
            return null;
        }
        LambdaQueryWrapper<SysPermissionEntity> queryWrapper = Wrappers.<SysPermissionEntity>lambdaQuery().in(SysPermissionEntity::getId, permissionIds).eq(SysPermissionEntity::getStatus, 1).orderByAsc(SysPermissionEntity::getOrderNum);
        return sysPermissionMapper.selectList(queryWrapper);
    }

    /**
     * 删除菜单权限
     * 判断是否 有角色关联
     * 判断是否有子集
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleted(String permissionId) {
        SysPermissionEntity sysPermission = sysPermissionMapper.selectById(permissionId);
        if (null == sysPermission) {
            throw new BusinessException(BaseResponseCode.DATA_ERROR);
        }
        //获取下一级
        List<SysPermissionEntity> childs = sysPermissionMapper.selectList(Wrappers.<SysPermissionEntity>lambdaQuery().eq(SysPermissionEntity::getPid, permissionId));
        if (!CollectionUtils.isEmpty(childs)) {
            throw new BusinessException(BaseResponseCode.ROLE_PERMISSION_RELATION);
        }
        sysPermissionMapper.deleteById(permissionId);
        //删除和角色关联
        sysRolePermissionMapper.delete(Wrappers.<SysRolePermissionEntity>lambdaQuery().eq(SysRolePermissionEntity::getPermissionId, permissionId));

    }

    @Override
    public void updatePermission(SysPermissionEntity vo) {
        AssertUtil.isStringNotBlank(vo.getId(), "id不能为空");
        SysPermissionEntity sysPermission = sysPermissionMapper.selectById(vo.getId());
        if (null == sysPermission) {
            throw new BusinessException(BaseResponseCode.DATA_ERROR);
        }
        // 只有类型变更或者所属菜单变更
        if (sysPermission.getType().equals(vo.getType()) || !sysPermission.getPid().equals(vo.getPid())) {
            verifyFormPid(vo);
        }
        sysPermissionMapper.updateById(vo);
    }

    /**
     * 获取所有菜单权限
     */
    @Override
    public List<SysPermissionResp> selectAll(Integer status) {
        List<SysPermissionEntity> result = sysPermissionMapper.selectList(Wrappers.<SysPermissionEntity>lambdaQuery().eq(status != null, SysPermissionEntity::getStatus, status).orderByAsc(SysPermissionEntity::getOrderNum));
        if (!CollectionUtils.isEmpty(result)) {
            return result.stream().map(sysPermission -> {
                SysPermissionResp convert = ConvertUtils.convert(sysPermission, SysPermissionResp.class);
                SysPermissionEntity parent = sysPermissionMapper.selectById(sysPermission.getPid());
                if (parent != null) {
                    convert.setPidName(parent.getName());
                }
                return convert;
            }).collect(Collectors.toList());

        }
        return Collections.emptyList();
    }

    /**
     * 获取权限标识
     */
    @Override
    public List<String> getPermissionsByUserId(String userId) {

        List<SysPermissionEntity> list = getPermission(userId);
        Set<String> permissions = new HashSet<>();
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        for (SysPermissionEntity sysPermission : list) {
            if (!StringUtils.isEmpty(sysPermission.getPerms())) {
                permissions.add(sysPermission.getPerms());
            }

        }
        return new ArrayList<String>(permissions);
    }

    /**
     * 以树型的形式把用户拥有的菜单权限返回给客户端
     */
    @Override
    public List<PermissionNodeResp> permissionTreeList(String userId) {
        List<SysPermissionEntity> list = getPermission(userId);
        List<SysPermissionResp> sysPermissionRespList = ConvertUtils.convertList(list, SysPermissionResp.class);
        return getTree(sysPermissionRespList, true);
    }

    /**
     * 递归获取菜单树
     */
    private List<PermissionNodeResp> getTree(List<SysPermissionResp> all, boolean type) {

        List<PermissionNodeResp> list = new ArrayList<>();
        if (CollectionUtils.isEmpty(all)) {
            return list;
        }
        for (SysPermissionResp sysPermission : all) {
            if ("0".equals(sysPermission.getPid())) {
                PermissionNodeResp permissionRespNode = new PermissionNodeResp();
                BeanUtils.copyProperties(sysPermission, permissionRespNode);
                permissionRespNode.setTitle(sysPermission.getName());

                if (type) {
                    permissionRespNode.setChildren(getChildExcBtn(sysPermission.getId(), all));
                } else {
                    permissionRespNode.setChildren(getChildAll(sysPermission.getId(), all));
                }
                list.add(permissionRespNode);
            }
        }
        return list;
    }

    /**
     * 递归遍历所有
     */
    private List<PermissionNodeResp> getChildAll(String id, List<SysPermissionResp> all) {

        List<PermissionNodeResp> list = new ArrayList<>();
        for (SysPermissionResp sysPermission : all) {
            if (sysPermission.getPid().equals(id)) {
                PermissionNodeResp permissionRespNode = new PermissionNodeResp();
                BeanUtils.copyProperties(sysPermission, permissionRespNode);
                permissionRespNode.setTitle(sysPermission.getName());
                permissionRespNode.setChildren(getChildAll(sysPermission.getId(), all));
                list.add(permissionRespNode);
            }
        }
        return list;
    }

    /**
     * 只递归获取目录和菜单
     */
    private List<PermissionNodeResp> getChildExcBtn(String id, List<SysPermissionResp> all) {

        List<PermissionNodeResp> list = new ArrayList<>();
        for (SysPermissionResp sysPermission : all) {
            if (sysPermission.getPid().equals(id) && sysPermission.getType() != 3) {
                PermissionNodeResp permissionRespNode = new PermissionNodeResp();
                BeanUtils.copyProperties(sysPermission, permissionRespNode);
                permissionRespNode.setTitle(sysPermission.getName());
                permissionRespNode.setChildren(getChildExcBtn(sysPermission.getId(), all));
                list.add(permissionRespNode);
            }
        }
        return list;
    }

    /**
     * 获取所有菜单权限按钮
     */
    @Override
    public List<PermissionNodeResp> selectAllByTree(Integer status) {

        List<SysPermissionResp> list = selectAll(status);
        return getTree(list, false);
    }

    /**
     * 获取所有的目录菜单树排除按钮
     * 因为不管是新增或者修改
     * 选择所属菜单目录的时候
     * 都不可能选择到按钮
     * 而且编辑的时候 所属目录不能
     * 选择自己和它的子类
     */
    @Override
    public List<PermissionNodeResp> selectAllMenuByTree(String permissionId) {

        List<SysPermissionResp> list = selectAll(1);
        if (!CollectionUtils.isEmpty(list) && !StringUtils.isEmpty(permissionId)) {
            for (SysPermissionResp sysPermission : list) {
                if (sysPermission.getId().equals(permissionId)) {
                    list.remove(sysPermission);
                    break;
                }
            }
        }
        List<PermissionNodeResp> result = new ArrayList<>();
        //新增顶级目录是为了方便添加一级目录
        PermissionNodeResp respNode = new PermissionNodeResp();
        respNode.setId("0");
        respNode.setTitle("默认顶级菜单");
        respNode.setSpread(true);
        respNode.setChildren(getTree(list, true));
        result.add(respNode);
        return result;
    }

    @Override
    public List<String> getUserIdsById(String id) {
        //根据权限id，获取所有角色id
        //根据权限id，获取所有角色id
        List<String> roleIds = rolePermissionService.getRoleIds(id);
        if (!CollectionUtils.isEmpty(roleIds)) {
            List<SysUserRoleEntity> sysUserRoles = sysUserRoleMapper.selectList(Wrappers.<SysUserRoleEntity>lambdaQuery().select(SysUserRoleEntity::getUserId).in(SysUserRoleEntity::getRoleId, roleIds));
            //根据角色id， 获取关联用户
            return sysUserRoles.stream().map(SysUserRoleEntity::getUserId).collect(Collectors.toList());
        }
        return null;
    }


}
